﻿using System.Collections.Generic;
using UnityEngine.UIElements;

namespace winS.UnityEditor.UIElement
{
    /// <summary>
    /// Element container that can slide horizontally.
    /// Each element has same fixed width.
    /// </summary>
    public class HorizontalSlideView : VisualElement
    {
        public static readonly float defaultSlideDuration = 0.24f;

        public int index { get; private set; }
        public float slideDuration { get => _slideDuration; set => SetSlideDuration(value); }

        private readonly VisualElement mask;
        private readonly VisualElement itemContainer;

        private float currentWidth;
        private float _slideDuration = defaultSlideDuration;

        public HorizontalSlideView()
        {
            style.overflow = Overflow.Hidden;
            base.Add(mask = new VisualElement());
            mask.style.overflow = Overflow.Hidden;
            mask.style.SetFixedWidth(100f, LengthUnit.Percent);
            mask.Add(itemContainer = new VisualElement());
            itemContainer.style.flexDirection = FlexDirection.Row;
            itemContainer.style.SetTransition("height", EasingMode.EaseOutCirc);
            itemContainer.usageHints = UsageHints.GroupTransform;

            mask.style.flexGrow = itemContainer.style.flexGrow = 1f;

            slideDuration = defaultSlideDuration;
            RegisterCallback<GeometryChangedEvent>(GeometryChangedCallback);
        }

        public new void Clear()
        {
            itemContainer.Clear();
        }
        public new void Add(VisualElement content)
        {
            VisualElement item = new VisualElement();
            item.style.flexBasis = 0f;
            item.style.flexShrink = 0f;
            item.Add(content);
            itemContainer.Add(item);
        }
        public void SlideContent(int index, bool animation = true)
        {
            this.index = index;
            if (panel == null) return;
            if (animation) itemContainer.style.left = -index * currentWidth;
            else RebuildLayout();
        }

        private void RebuildLayout()
        {
            style.transitionProperty = mask.style.transitionProperty = itemContainer.style.transitionProperty = EditorElementUtility.emptyPropertyList;

            itemContainer.style.left = -index * currentWidth;

            style.transitionProperty = mask.style.transitionProperty = EditorElementUtility.widthPropertyList;
            itemContainer.style.transitionProperty = EditorElementUtility.leftPropertyList;
        }
        private void SetSlideDuration(float newValue)
        {
            _slideDuration = newValue;
            style.transitionProperty = mask.style.transitionProperty = EditorElementUtility.widthPropertyList;
            itemContainer.style.transitionProperty = EditorElementUtility.leftPropertyList;

            style.transitionDuration = mask.style.transitionDuration = itemContainer.style.transitionDuration = new List<TimeValue>() { _slideDuration };
        }
        private void GeometryChangedCallback(GeometryChangedEvent geometryChangedEvent)
        {
            currentWidth = geometryChangedEvent.newRect.width;
            foreach (var item in itemContainer.Children()) item.style.SetFixedWidth(currentWidth);
            RebuildLayout();
        }
    }
}